package com.jiang.test;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class Cache<K, V> {

	private ConcurrentHashMap<K, V> map = new ConcurrentHashMap<K, V>(); // 真正存储数据
	private DelayQueue<DelayItem<Pair>> queue = new DelayQueue<DelayItem<Pair>>();

	private class Pair { //一定要包一层，不包一层的话后面延迟弹出后，map就不好删除了
		private K key;
		private V value;

		public Pair(K key, V value) {
			this.key = key;
			this.value = value;
		}
	}

	public Cache() {
		// 启动守护线程
		Thread t = new Thread(() -> {

			while (true) {
				try {
					DelayItem<Pair> delayItem = this.queue.take();
					if (delayItem != null) {
						Pair pair = delayItem.getItem();
						// 从Map中删除
						map.remove(pair.key, pair.value);
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

			}

		}, "守护线程");
		t.setDaemon(true);// 成为后台线程
		t.start();
	}

	public void put(K key, V value, long time, TimeUnit unit) {

		V oldValue = this.map.put(key, value);
		if (oldValue != null) {
			this.queue.remove(oldValue); // 队列中存在旧的值删除掉
		}
		this.queue.put(new DelayItem<Pair>(new Pair(key, value), time, unit));

	}

	public V get(K key) {

		return this.map.get(key);

	}

}

class DelayItem<T> implements Delayed {

	private T item;
	private long delay;
	private long expire;

	public DelayItem(T item, long delay, TimeUnit unit) {
		this.item = item;
		this.delay = TimeUnit.MILLISECONDS.convert(delay, unit);
		this.expire = System.currentTimeMillis() + this.delay;
	}

	@Override
	public int compareTo(Delayed o) {

		return (int) (this.delay - getDelay(TimeUnit.MILLISECONDS));

	}

	@Override
	public long getDelay(TimeUnit unit) {

		return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);

	}

	public T getItem() {
		return this.item;
	}

}